#include "analyzer.h"

Analyzer::Analyzer(QObject *parent) : QObject(parent)
{
    isTest=false;
    isDebug=false;
}

Analyzer::~Analyzer()
{
    if(logFile.isOpen())
        logFile.close();
}

void Analyzer::log(const QString &message)
{
    if(isTest)
    {
        qDebug() << message;
        return;
    }

    if(logFile.isOpen())
    {
        if(isDebug)
            out << "[Debug]" + message << Qt::endl;
        else
            out << message << Qt::endl;
    }
    else
        popMessage(QString("无法打开日志文件, 错误信息：%1, 日志信息： %2")
                   .arg(logFile.errorString())
                   .arg(message));
}

void Analyzer::onAwake()
{
    logFile.setFileName(QString("%1-%2.log")
                        .arg(SP_NAME)
                        .arg(QDate::currentDate().toString("yyyyMMdd")));

    if(!logFile.open(QFile::Append | QFile::Text))
    {
        popMessage(QString("无法打开日志文件, 错误信息：%1")
                   .arg(logFile.errorString()));
    }
    else
    {
        out.setDevice(&logFile);
        out.setCodec("UTF-8");
        log(QString("[%1] %2 已启动，当前版本 %3")
            .arg(CurrentDateTime)
            .arg(SP_NAME).arg(SP_VER));
    }
    auto dsn=odbc_genDSN(U8DB_HOST,U8DB_PORT,U8DB_USER,U8DB_PASSWD,U8DB_DBNAME);
    odbc=odbc_getConnection(dsn,SQL_U8_CONNECTION);

    if(odbc.open())
    {
        awake(true);
        log("数据库已连接，可以执行操作");
    }
    else
    {
        awake(false);
        log("数据库无法连接，错误信息：" + odbc.lastError().text());
    }
}

void Analyzer::onDebug()
{
    logFile.setFileName(QString("%1-%2.debug.log")
                        .arg(SP_NAME)
                        .arg(QDate::currentDate().toString("yyyyMMdd")));

    if(!logFile.open(QFile::Append | QFile::Text))
    {
        popMessage(QString("无法打开日志文件, 错误信息：%1")
                   .arg(logFile.errorString()));
    }
    else
    {
        isDebug=true;
        out.setDevice(&logFile);
        out.setCodec("UTF-8");
        log(QString("[%1] %2 已启动，当前版本 %3")
            .arg(CurrentDateTime)
            .arg(SP_NAME).arg(SP_VER));
    }

    auto dsn=odbc_genDSN(U8DB_HOST,U8DB_PORT,U8DB_USER,U8DB_PASSWD,U8DB_DBNAME);
    odbc=odbc_getConnection(dsn,SQL_U8_CONNECTION);

    if(odbc.open())
    {
        awake(true);
        log("数据库已连接，可以执行操作");
    }
    else
    {
        awake(false);
        log("数据库无法连接，错误信息：" + odbc.lastError().text());
    }
}

void Analyzer::onAnalyze(const QString &beginDate)
{
    analyzing(true);
    analyze_DL(beginDate);
    analyze_EB(beginDate);
    analyzing(false);

    if(isDebug)
    {
        log(QString("%1 操作完成，程序现在退出").arg(CurrentDateTime));
        QCoreApplication::quit();
    }
}

int Analyzer::getStock(const QString &invCode)
{
    int result = 0;
    QSqlQuery query(odbc);
    auto sql=QString("select sum(iQuantity) as total from CurrentStock where cInvCode='%1' AND cWhCode in ('001','003')")
            .arg(invCode);
    if(isTest || isDebug)
        log(sql);

    query.exec(sql);
    if(query.next())
    {
        result = query.value(0).toInt();
        stockCache.insert(invCode,result);
    }

    return result;
}

void Analyzer::reset_DL(const QString &beginDate)
{
    if(!odbc.isOpen())
    {
        log("数据库连接异常，操作终止");
        return;
    }

    if(!stockCache.isEmpty())
        stockCache.clear();

    QSqlQuery query(odbc);
    auto sql=QString("update DispatchList set cDefine15=null where dDate >= '%1'")
            .arg(beginDate);
    if(isTest || isDebug)
        log(sql);

    bool result=query.exec(sql);
    if(result)
        log(QString("[%1] 操作完成，发货单标记已清除")
            .arg(CurrentDateTime));
    else
        log(QString("[%1] 操作失败，错误信息：%2")
            .arg(CurrentDateTime).arg(query.lastError().text()));

}

void Analyzer::analyze_DL(const QString &beginDate)
{
    if(!odbc.isOpen())
    {
        log("数据库连接异常，操作终止");
        return;
    }

    log(QString("[%1] 发货单筛选开始--").arg(CurrentDateTime));

    reset_DL(beginDate);

    // 审核中，非退货
    QSqlQuery query(odbc);
    auto sql=QString("select DLID,cCusCode from DispatchList where dDate >= '%1' and iverifystate=1 and bReturnFlag=0")
            .arg(beginDate);
    if(isTest || isDebug)
        log(sql);

    query.exec(sql);
    int row=0,flag=0;
    while (query.next()) {
        auto dlid=query.value(0).toString();
        auto cCusCode=query.value(1).toString();

        bool spec=false;
        if(cCusCode == "C07" || cCusCode == "0000D007841")
        {
            if(isTest || isDebug)
                log(QString("检测到特殊客户，DLID: %1，cCusCode: %2")
                    .arg(dlid).arg(cCusCode));
            spec=true;
        }

        if(itemAnalyze_DL(dlid,spec))
        {
            if(tagUp_DL(dlid))
            {
                // log(QString("%1 符合发货条件，已标记").arg(cDLCode));
                flag +=1;
            }
        }
        row += 1;
    }
    log(QString("[%1] 发货单筛选完成，本次共处理 %2 条，标记 %3 条")
        .arg(CurrentDateTime).arg(row).arg(flag));
}

bool Analyzer::itemAnalyze_DL(const QString &dlid, bool spec)
{
    int flag=0;
    QSqlQuery query(odbc);
    auto sql=QString("select cInvCode,sum(iQuantity) as delivery from DispatchLists where DLID='%1' group by cInvCode")
            .arg(dlid);
    if(isTest || isDebug)
        log(sql);

    query.exec(sql);
    while (query.next()) {
        auto invCode=query.value(0).toString();
        auto delivery=query.value(1).toInt();  // 出库数量
        if(invCode == "txfwf-1")
        {
            if(isTest || isDebug)
                log("检测到txfwf-1，跳过");
            continue;
        }
        if(!cellAnalyze_DL(invCode,delivery,spec))
            flag+=1;
    }
    return flag==0;
}

// 发货单-线下筛选
bool Analyzer::action_cellAnalyze_DL(const QString &invCode, int stock, int delivery, int reserve, int restriction)
{
    if(restriction > 0)
    {
        if( (stock - reserve - delivery) >= 0 && delivery <= restriction)
        {
            stock = stock - delivery;
            stockCache.insert(invCode,stock);
            return true;
        }
        else
            return false;
    }
    else
    {
        if( (stock - reserve - delivery) >= 0 )
        {
            stock = stock - delivery;
            stockCache.insert(invCode,stock);
            return true;
        }
        else
            return false;
    }
}

bool Analyzer::cellAnalyze_DL(const QString &invCode, int delivery, bool spec)
{
    int stock=0;
    if(stockCache.contains(invCode))
        stock=stockCache.value(invCode);
    else
        stock=getStock(invCode);

    if(stock <= 0 || stock < delivery)
    {
        if(isTest || isDebug)
            log(QString("%1 现存量小于等于0 或者 现存量小于发货数量，跳过").arg(invCode));
        return false;
    }

    QSqlQuery query(odbc);
    auto sql=QString("select cInvDefine11,cInvDefine12 from Inventory where cInvCode='%1'")
            .arg(invCode);
    if(isTest || isDebug)
        log(sql);

    query.exec(sql);
    if(query.next())
    {
        auto reserve=query.value(0).toInt();    //电商留存数
        auto restriction=query.value(1).toInt();    //发货限制数

        if(isTest || isDebug)
            log(QString("正在检测 %1, 现存量 %2, 电商留存数 %3, 发货限制数 %4")
                .arg(invCode).arg(stock).arg(reserve).arg(restriction));

        // 如果是特殊订单，就要按照电商规则筛选
        if(spec)
            return action_cellAnalyze_EB(invCode,stock,delivery,restriction);
        else
            return action_cellAnalyze_DL(invCode,stock,delivery,reserve,restriction);

    }
    return false;
}

bool Analyzer::tagUp_DL(const QString &dlid)
{
    QSqlQuery query(odbc);
    auto sql=QString("update DispatchList set cDefine15=1 where DLID='%1'")
            .arg(dlid);
    if(isTest || isDebug)
        log(sql);

    bool result=query.exec(sql);
    if(result)
        return true;
    else
    {
        qDebug() << query.lastError().text();
        return false;
    }
}

void Analyzer::onTest_DL(const QString &cDLCode)
{
    if(!odbc.isOpen())
    {
        log("数据库连接异常，操作终止");
        return;
    }

    isTest=true;
    log(QString("现在开始测试，发货单号 %1").arg(cDLCode));

    QSqlQuery query(odbc);
    auto sql=QString("select DLID,cCusCode from DispatchList where cDLCode='%1'")
            .arg(cDLCode);
    if(isTest || isDebug)
        log(sql);

    query.exec(sql);
    if(query.next())
    {
        auto dlid=query.value(0).toString();
        auto cCusCode=query.value(1).toString();

        bool spec=false;
        if(cCusCode == "C07" || cCusCode == "0000D007841")
        {
            if(isTest || isDebug)
                log(QString("检测到特殊客户，DLID: %1，cCusCode: %2")
                    .arg(dlid).arg(cCusCode));
            spec=true;
        }

        log(QString("已查询到DLID %1").arg(dlid));
        if(itemAnalyze_DL(dlid,spec))
        {
            log("测试完成，符合发货条件");
        }
        else
            log("测试完成，不符合发货条件");
    }
    else
        log("未查询到DLID，测试终止");

    QCoreApplication::quit();
}


void Analyzer::reset_EB(const QString &beginDate)
{
    if(!odbc.isOpen())
    {
        log("数据库连接异常，操作终止");
        return;
    }

    /*
    if(!stockCache.isEmpty())
        stockCache.clear();
   */

    QSqlQuery query(odbc);
    bool result=query.exec(QString("update EB_Trade set cDefine15=null,cExcoPrintStatus=0 where created >= '%1'")
                           .arg(beginDate));
    if(result)
        log(QString("[%1] 操作完成，电商标记已清除")
            .arg(CurrentDateTime));
    else
        log(QString("[%1] 操作失败，错误信息：%2")
            .arg(CurrentDateTime).arg(query.lastError().text()));
}

void Analyzer::analyze_EB(const QString &beginDate)
{
    if(!odbc.isOpen())
    {
        log("数据库连接异常，操作终止");
        return;
    }

    log(QString("[%1] 电商订单筛选开始--").arg(CurrentDateTime));

    reset_EB(beginDate);

    // 审核中，非退货
    QSqlQuery query(odbc);
    query.exec(QString("select autoID from EB_Trade where sysStatus='Effective' AND created >= '%1' AND isHold=0")
               .arg(beginDate));
    int row=0,flag=0;
    while (query.next()) {
        auto autoID=query.value(0).toString();
        if(itemAnalyze_EB(autoID))
        {
            if(tagUp_EB(autoID))
            {
                flag +=1;
            }
        }
        row += 1;
    }
    log(QString("[%1] 电商订单筛选完成，本次共处理 %2 条，标记 %3 条")
        .arg(CurrentDateTime).arg(row).arg(flag));
}

bool Analyzer::itemAnalyze_EB(const QString &autoID)
{
    int flag=0;
    QSqlQuery query(odbc);
    auto sql=QString("select cInvCode,num from EB_Order as eo JOIN EB_Item as ei ON eo.cItemID=ei.OID where parentID='%1'")
            .arg(autoID);
    if(isTest || isDebug)
        log(sql);

    query.exec(sql);
    while (query.next()) {
        auto invCode=query.value(0).toString();
        auto delivery=query.value(1).toInt();  // 出库数量
        if(invCode == "txfwf-1")
        {
            if(isTest || isDebug)
                log("检测到txfwf-1，跳过");
            continue;
        }

        if(!cellAnalyze_EB(invCode,delivery))
            flag+=1;
    }
    return flag==0;
}

// 线上-电商订单筛选
bool Analyzer::action_cellAnalyze_EB(const QString &invCode, int stock, int delivery, int restriction)
{
    if(restriction > 0)
    {
        if( stock >= delivery && delivery <= restriction)
        {
            stock = stock - delivery;
            stockCache.insert(invCode,stock);
            return true;
        }
        else
            return false;
    }
    else
    {
        if( stock >= delivery )
        {
            stock = stock - delivery;
            stockCache.insert(invCode,stock);
            return true;
        }
        else
            return false;
    }
}

bool Analyzer::cellAnalyze_EB(const QString &invCode, int delivery)
{
    int stock=0;
    if(stockCache.contains(invCode))
        stock=stockCache.value(invCode);
    else
        stock=getStock(invCode);

    if(stock <= 0 || stock < delivery)
    {
        if(isTest || isDebug)
            log(QString("%1 现存量小于等于0 或者 现存量小于发货数量，跳过").arg(invCode));
        return false;
    }

    QSqlQuery query(odbc);
    auto sql=QString("select cInvDefine12 from Inventory where cInvCode='%1'")
            .arg(invCode);
    if(isTest)
        log(sql);

    query.exec(sql);
    if(query.next())
    {
        auto restriction=query.value(0).toInt();    //发货限制数

        if(isTest || isDebug)
            log(QString("正在检测 %1, 现存量 %2, 发货限制数 %3")
                .arg(invCode).arg(stock).arg(restriction));

        return action_cellAnalyze_EB(invCode,stock,delivery,restriction);
    }
    return false;
}

bool Analyzer::tagUp_EB(const QString &autoID)
{
    QSqlQuery query(odbc);
    bool result=query.exec(QString("update EB_Trade set cExcoPrintStatus=1,cDefine15=1 where autoID='%1'")
                           .arg(autoID));
    if(result)
        return true;
    else
    {
        qDebug() << query.lastError().text();
        return false;
    }
}

void Analyzer::onTest_EB(const QString &cTradeCode)
{
    if(!odbc.isOpen())
    {
        log("数据库连接异常，操作终止");
        return;
    }

    isTest=true;
    log(QString("现在开始测试，电商订单号 %1").arg(cTradeCode));

    QSqlQuery query(odbc);
    auto sql=QString("select autoID,cTradeCode from EB_Trade where cTradeCode='%1'")
            .arg(cTradeCode);
    if(isTest || isDebug)
        log(sql);

    query.exec(sql);
    if(query.next())
    {
        auto autoID=query.value(0).toString();
        if(itemAnalyze_EB(autoID))
        {
            log("测试完成，符合发货条件");
        }
        else
            log("测试完成，不符合发货条件");
    }
    else
        log("未查询到电商订单号，测试终止");

    QCoreApplication::quit();
}
